package com.service.component.relation.services.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.service.component.common.CommonResult;
import com.service.component.group.entity.Group;
import com.service.component.group.mapper.GroupMapper;
import com.service.component.permissions.entity.Permission;
import com.service.component.permissions.mapper.PermissionMapper;
import com.service.component.permissions.services.PermissionService;
import com.service.component.relation.entity.*;
import com.service.component.relation.mapper.*;
import com.service.component.relation.services.RelationServices;
import com.service.component.role.entity.Role;
import com.service.component.role.mapper.RoleMapper;
import com.service.component.role.services.RoleServices;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * @author ：Calvin
 * @create ：2021/7/23 10:38
 * @description：关联关系服务的实现
 * @modified By：
 * @version: 1.0.0$
 */
@Service
public class RelationServiceImpl<T> implements RelationServices<T> {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private GroupMapper groupMapper;
    @Autowired
    private GroupPremRelationMapper groupPremRelationMapper;
    @Autowired
    private GroupRoleRelationMapper groupRoleRelationMapper;
    @Autowired
    private RolePremRelationMapper rolePremRelationMapper;
    @Autowired
    private UserGroupRelationMapper userGroupRelationMapper;
    @Autowired
    private UserPremRelationMapper userPremRelationMapper;
    @Autowired
    private UserRoleRelationMapper userRoleRelationMapper;
    @Autowired
    private GroupFilterPremRelationMapper groupFilterPremRelationMapper;
    @Autowired
    private GroupFilterRoleRelationMapper groupFilterRoleRelationMapper;
    @Autowired
    private UserFilterPremRelationMapper userFilterPremRelationMapper;
    @Autowired
    private UserFilterRoleRelationMapper userFilterRoleRelationMapper;

    @Override
    public List<Role> getUserRolesByUserId(String userId) {
        List<String> roleIdsByUserId = getUserRoleIdsByUserId(userId);
        List<Role> roleList = roleMapper.selectBatchIds(roleIdsByUserId);
        //由于高级角色包含低角色，所以需要查询子角色(如总监的角色包含员工角色)
        roleList.addAll(CollectionUtils.isNotEmpty(roleIdsByUserId) ? roleMapper.selectList(new QueryWrapper<Role>().in("PARENT_ID", roleIdsByUserId)) : new ArrayList<>());
        //由于父子权限和组权限都有可能重复，所以根据权限id去重
        List<Role> collect = roleList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<Role>(Comparator.comparing(Role::getId))), ArrayList::new));
        return CollectionUtils.isNotEmpty(roleIdsByUserId) ? collect : new ArrayList<>();
    }

    /**
     * 根据用户Id查询所有角色
     *
     * @param userId
     * @return
     */
    private List<String> getUserRoleIdsByUserId(String userId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("USER_ID", userId);
        //用户角色
        List<UserRoleRelation> userRoleRelationsList = userRoleRelationMapper.selectList(queryWrapper);
        List<UserFilterRoleRelation> userFilterRoleRelationList = userFilterRoleRelationMapper.selectList(queryWrapper);
        //从用户角色中过滤掉所有的负角色
        userRoleRelationsList = userRoleRelationsList.stream().filter(
                (userRoleRelation) -> !userFilterRoleRelationList.stream().map(UserFilterRoleRelation::getRoleId).collect(Collectors.toList()).contains(userRoleRelation.getRoleId())
        ).collect(Collectors.toList());
        //组角色
        List<UserGroupRelation> userGroupRelationList = userGroupRelationMapper.selectList(queryWrapper);
        List<String> groupIds = userGroupRelationList.stream().map(UserGroupRelation::getGroupId).collect(Collectors.toList());
        List<GroupRoleRelation> groupRoleRelationList = queryGroupRole(groupIds);
        //获取所有的角色id
        List<String> roleIds = userRoleRelationsList.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());
        roleIds.addAll(groupRoleRelationList.stream().map(GroupRoleRelation::getRoleId).collect(Collectors.toList()));
        return roleIds;
    }

    /**
     * 根据组id的集合批量查询所有的角色，单个也可以
     *
     * @param groupIds 组集合id
     * @return 组拥有的角色
     */
    private List<GroupRoleRelation> queryGroupRole(List<String> groupIds) {
        QueryWrapper query = new QueryWrapper();
        if (CollectionUtils.isNotEmpty(groupIds)) {
            query.in("GROUP_ID", groupIds);
        }
        List<GroupRoleRelation> groupRoleRelationList = groupRoleRelationMapper.selectList(query);
        List<GroupFilterRoleRelation> groupFilterRoleRelationList = groupFilterRoleRelationMapper.selectList(query);
        //从组角色中过滤掉所有的负角色
        groupRoleRelationList = groupRoleRelationList.stream().filter(
                (groupRoleRelation) -> !groupFilterRoleRelationList.stream().map(GroupFilterRoleRelation::getRoleId).collect(Collectors.toList()).contains(groupRoleRelation.getRoleId())
        ).collect(Collectors.toList());
        return groupRoleRelationList;
    }


    @Override
    public List<Permission> getUserPermissionByUserId(String userId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("USER_ID", userId);
        //查询用户本身的权限
        List<UserPremRelation> userPremRelationList = userPremRelationMapper.selectList(queryWrapper);
        List<UserFilterPermRelation> userFilterPermRelationsList = userFilterPremRelationMapper.selectList(queryWrapper);
        //从用户权限中过滤掉所有的负权限
        userPremRelationList = userPremRelationList.stream().filter(
                (userPremRelation) -> !userFilterPermRelationsList.stream().map(UserFilterPermRelation::getPermId).collect(Collectors.toList()).contains(userPremRelation.getPermId())
        ).collect(Collectors.toList());
        //根据用户Id查询所归属的组,并且查询所有组拥有的权限
        List<UserGroupRelation> userGroupRelationList = userGroupRelationMapper.selectList(queryWrapper);
        List<String> groupIds = userGroupRelationList.stream().map(UserGroupRelation::getGroupId).collect(Collectors.toList());
        List<GroupPremRelation> groupPremRelationList = queryGroupPerm(groupIds);
        //查询用户所归属的角色(该用户所拥有的权限包含该用户所归属的组角色所拥有的所有权限)，并且该角色具有的所有权限
        List<String> roleIdsByUserId = getUserRoleIdsByUserId(userId);
        QueryWrapper queryRolePermsByRoleIds = new QueryWrapper();
        if (CollectionUtils.isNotEmpty(roleIdsByUserId)) {
            queryRolePermsByRoleIds.in("ROLE_ID", roleIdsByUserId);
        }
        List<RolePremRelation> rolePremRelationList = rolePremRelationMapper.selectList(queryRolePermsByRoleIds);
        //获取所有的权限id
        List<String> permIds = userPremRelationList.stream().map(UserPremRelation::getPermId).collect(Collectors.toList());
        permIds.addAll(groupPremRelationList.stream().map(GroupPremRelation::getPermId).collect(Collectors.toList()));
        permIds.addAll(rolePremRelationList.stream().map(RolePremRelation::getPermId).collect(Collectors.toList()));
        List<Permission> permissions = CollectionUtils.isNotEmpty(permIds) ? permissionMapper.selectBatchIds(permIds) : new ArrayList<>();
        //由于高权限可以拥有低权限，所以获取所有的子权限并授权
        permissions.addAll(CollectionUtils.isNotEmpty(permIds) ? permissionMapper.selectList(new QueryWrapper<Permission>().in("PARENT_ID", permIds)) : new ArrayList<>());
        //由于父子权限和组权限都有可能重复，所以根据权限id去重
        List<Permission> collect = permissions.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<Permission>(Comparator.comparing(Permission::getId))), ArrayList::new));
        return CollectionUtils.isNotEmpty(permIds) ? collect : new ArrayList<>();
    }

    @Override
    public CommonResult deleteUserFilterPermByUserIdAndPermId(String userId, String PermId) {
        QueryWrapper<UserFilterPermRelation> queryWrapper = new QueryWrapper<UserFilterPermRelation>();
        queryWrapper.eq("USER_ID", userId);
        queryWrapper.eq("PERM_ID", PermId);
        return userFilterPremRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    /**
     * 删除用户负角色
     *
     * @param userId 用户id
     * @param roleId 角色id
     * @return 成功与否
     */
    @Override
    public CommonResult deleteUserFilterRoleByUserIdAndPermId(String userId, String roleId) {
        QueryWrapper<UserFilterRoleRelation> queryWrapper = new QueryWrapper<UserFilterRoleRelation>();
        queryWrapper.eq("USER_ID", userId);
        queryWrapper.eq("ROLE_ID", roleId);
        return userFilterRoleRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    @Override
    public CommonResult deleteGroupFilterPermByUserIdAndPermId(String groupId, String PermId) {
        QueryWrapper<GroupFilterPermRelation> queryWrapper = new QueryWrapper<GroupFilterPermRelation>();
        queryWrapper.eq("GROUP_ID", groupId);
        queryWrapper.eq("PERM_ID", PermId);
        return groupFilterPremRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    @Override
    public CommonResult deleteGroupFilterRoleByUserIdAndPermId(String groupId, String roleId) {
        QueryWrapper<GroupFilterRoleRelation> queryWrapper = new QueryWrapper<GroupFilterRoleRelation>();
        queryWrapper.eq("GROUP_ID", groupId);
        queryWrapper.eq("ROLE_ID", roleId);
        return groupFilterRoleRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }


    @Override
    public CommonResult deleteUserPermByUserIdAndPermId(String userId, String PermId) {
        QueryWrapper<UserPremRelation> queryWrapper = new QueryWrapper<UserPremRelation>();
        queryWrapper.eq("USER_ID", userId);
        queryWrapper.eq("PERM_ID", PermId);
        return userPremRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    @Override
    public CommonResult deleteUserGroupByUserIdAndPermId(String userId, String groupId) {
        QueryWrapper<UserGroupRelation> queryWrapper = new QueryWrapper<UserGroupRelation>();
        queryWrapper.eq("USER_ID", userId);
        queryWrapper.eq("GROUP_ID", groupId);
        return userGroupRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    @Override
    public CommonResult deleteRolePermByRoleIdAndPermId(String roleId, String permId) {
        QueryWrapper<RolePremRelation> queryWrapper = new QueryWrapper<RolePremRelation>();
        queryWrapper.eq("ROLE_ID", roleId);
        queryWrapper.eq("PERM_ID", permId);
        return rolePremRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    /**
     * 删除用户负角色
     *
     * @param userId 用户id
     * @param roleId 角色id
     * @return 成功与否
     */
    @Override
    public CommonResult deleteUserRoleByUserIdAndPermId(String userId, String roleId) {
        QueryWrapper<UserRoleRelation> queryWrapper = new QueryWrapper<UserRoleRelation>();
        queryWrapper.eq("USER_ID", userId);
        queryWrapper.eq("ROLE_ID", roleId);
        return userRoleRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    @Override
    public CommonResult deleteGroupPermByUserIdAndPermId(String groupId, String PermId) {
        QueryWrapper<GroupPremRelation> queryWrapper = new QueryWrapper<GroupPremRelation>();
        queryWrapper.eq("GROUP_ID", groupId);
        queryWrapper.eq("PERM_ID", PermId);
        return groupPremRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    @Override
    public CommonResult deleteGroupRoleByUserIdAndPermId(String groupId, String roleId) {
        QueryWrapper<GroupRoleRelation> queryWrapper = new QueryWrapper<GroupRoleRelation>();
        queryWrapper.eq("GROUP_ID", groupId);
        queryWrapper.eq("ROLE_ID", roleId);
        return groupRoleRelationMapper.delete(queryWrapper) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }

    /**
     * 根据组id的集合批量查询所有的权限，单个也可以
     *
     * @param groupIds 组集合id
     * @return 组拥有的权限
     */
    private List<GroupPremRelation> queryGroupPerm(List<String> groupIds) {
        QueryWrapper query = new QueryWrapper();
        if (CollectionUtils.isNotEmpty(groupIds)) {
            query.in("GROUP_ID", groupIds);
        }
        List<GroupPremRelation> groupPremRelationList = groupPremRelationMapper.selectList(query);
        List<GroupFilterPermRelation> groupFilterPermRelationList = groupFilterPremRelationMapper.selectList(query);
        //从组权限中过滤掉所有的负权限
        groupPremRelationList = groupPremRelationList.stream().filter(
                (groupPremRelation) -> !groupFilterPermRelationList.stream().map(GroupFilterPermRelation::getPermId).collect(Collectors.toList()).contains(groupPremRelation.getPermId())
        ).collect(Collectors.toList());
        return groupPremRelationList;
    }

    /**
     * 新增或修改
     */
    @Override
    public CommonResult insertOrUpdateRelation(T t) {
        QueryWrapper queryWrapper = new QueryWrapper();
        //组权限处理
        if (t instanceof GroupPremRelation) {
            GroupPremRelation groupPremRelationParam = (GroupPremRelation) t;
            queryWrapper.eq("GROUP_ID", groupPremRelationParam.getGroupId());
            queryWrapper.eq("PERM_ID", groupPremRelationParam.getPermId());
            GroupPremRelation groupPremRelation = groupPremRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(groupPremRelation)) {
                if (StringUtils.equalsIgnoreCase(groupPremRelation.getPermType(), groupPremRelationParam.getPermType())) {
                    return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
                } else {
                    groupPremRelation.setPermType(groupPremRelationParam.getPermType());
                    return groupPremRelationMapper.updateById(groupPremRelation) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
                }
            }
            return groupPremRelationMapper.insert(groupPremRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //组角色处理
        if (t instanceof GroupRoleRelation) {
            GroupRoleRelation groupRoleRelationParam = (GroupRoleRelation) t;
            queryWrapper.eq("GROUP_ID", groupRoleRelationParam.getGroupId());
            queryWrapper.eq("ROLE_ID", groupRoleRelationParam.getRoleId());
            GroupRoleRelation groupRoleRelation = groupRoleRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(groupRoleRelation)) {
                return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
            }
            return groupRoleRelationMapper.insert(groupRoleRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //角色权限处理
        if (t instanceof RolePremRelation) {
            RolePremRelation rolePremRelationParam = (RolePremRelation) t;
            queryWrapper.eq("ROLE_ID", rolePremRelationParam.getRoleId());
            queryWrapper.eq("PERM_ID", rolePremRelationParam.getPermId());
            RolePremRelation rolePremRelation = rolePremRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(rolePremRelation)) {
                if (StringUtils.equalsIgnoreCase(rolePremRelation.getPermType(), rolePremRelationParam.getPermType())) {
                    return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
                } else {
                    rolePremRelation.setPermType(rolePremRelationParam.getPermType());
                    return rolePremRelationMapper.updateById(rolePremRelation) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
                }
            }
            return rolePremRelationMapper.insert(rolePremRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //用户组处理
        if (t instanceof UserGroupRelation) {
            UserGroupRelation userGroupRelationParam = (UserGroupRelation) t;
            queryWrapper.eq("USER_ID", userGroupRelationParam.getUserId());
            queryWrapper.eq("GROUP_ID", userGroupRelationParam.getGroupId());
            UserGroupRelation userGroupRelation = userGroupRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(userGroupRelation)) {
                return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
            }
            return userGroupRelationMapper.insert(userGroupRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //用户权限chuli
        if (t instanceof UserPremRelation) {
            UserPremRelation userPremRelationParam = (UserPremRelation) t;
            queryWrapper.eq("USER_ID", userPremRelationParam.getUserId());
            queryWrapper.eq("PERM_ID", userPremRelationParam.getPermId());
            UserPremRelation userPremRelation = userPremRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(userPremRelation)) {
                if (StringUtils.equalsIgnoreCase(userPremRelation.getPermType(), userPremRelationParam.getPermType())) {
                    return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
                } else {
                    userPremRelation.setPermType(userPremRelationParam.getPermType());
                    return userPremRelationMapper.updateById(userPremRelation) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
                }
            }
            return userPremRelationMapper.insert(userPremRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //用户角色处理
        if (t instanceof UserRoleRelation) {
            UserRoleRelation userRoleRelationParam = (UserRoleRelation) t;
            queryWrapper.eq("USER_ID", userRoleRelationParam.getUserId());
            queryWrapper.eq("ROLE_ID", userRoleRelationParam.getRoleId());
            UserRoleRelation userRoleRelation = userRoleRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(userRoleRelation)) {
                return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
            }
            return userRoleRelationMapper.insert(userRoleRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //用户负角色处理
        if (t instanceof UserFilterRoleRelation) {
            UserFilterRoleRelation userFilterRoleRelationParam = (UserFilterRoleRelation) t;
            queryWrapper.eq("USER_ID", userFilterRoleRelationParam.getUserId());
            queryWrapper.eq("ROLE_ID", userFilterRoleRelationParam.getRoleId());
            UserFilterRoleRelation userFilterRoleRelation = userFilterRoleRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(userFilterRoleRelation)) {
                return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
            }
            return userFilterRoleRelationMapper.insert(userFilterRoleRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //组负角色处理
        if (t instanceof GroupFilterRoleRelation) {
            GroupFilterRoleRelation groupFilterRoleRelationParam = (GroupFilterRoleRelation) t;
            queryWrapper.eq("GROUP_ID", groupFilterRoleRelationParam.getGroupId());
            queryWrapper.eq("ROLE_ID", groupFilterRoleRelationParam.getRoleId());
            GroupFilterRoleRelation groupFilterRoleRelation = groupFilterRoleRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(groupFilterRoleRelation)) {
                return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
            }
            return groupFilterRoleRelationMapper.insert(groupFilterRoleRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //用户负权限处理
        if (t instanceof UserFilterPermRelation) {
            UserFilterPermRelation userFilterPermRelationParam = (UserFilterPermRelation) t;
            queryWrapper.eq("USER_ID", userFilterPermRelationParam.getUserId());
            queryWrapper.eq("PERM_ID", userFilterPermRelationParam.getPermId());
            UserFilterPermRelation userFilterPermRelation = userFilterPremRelationMapper.selectOne(queryWrapper);
            if (ObjectUtils.isNotEmpty(userFilterPermRelation)) {
                return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
            }
            return userFilterPremRelationMapper.insert(userFilterPermRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
        }
        //组负权限处理
        GroupFilterPermRelation groupFilterPermRelationParam = (GroupFilterPermRelation) t;
        queryWrapper.eq("GROUP_ID", groupFilterPermRelationParam.getGroupId());
        queryWrapper.eq("PERM_ID", groupFilterPermRelationParam.getPermId());
        GroupFilterPermRelation groupFilterPermRelation = groupFilterPremRelationMapper.selectOne(queryWrapper);
        if (ObjectUtils.isNotEmpty(groupFilterPermRelation)) {
            return CommonResult.commonResult(CommonResult.ResultCode.DATA_EXIST);
        }
        return groupFilterPremRelationMapper.insert(groupFilterPermRelationParam) > 0 ? CommonResult.success() : CommonResult.commonResult(CommonResult.ResultCode.REQUEST_SQL_ERROR);
    }
}
